#ifndef _BASE_SDK_THREAD_CONTITION_H_
#define _BASE_SDK_THREAD_CONTITION_H_

#include "thread_mutex.h"

#ifndef WIN32
#include <sys/time.h>
class condition
{   
public:   
    condition (recursive_mutex &m)   
        : m_mutex (m)   
    {   
        pthread_cond_init(&m_convar, NULL);
    }   
    ~condition (void)   
    {   
        pthread_cond_destroy(&m_convar);
    }   
public:   
    // Returns a reference to the underlying mutex_;   
    recursive_mutex &mutex (void)   
    {   
        return m_mutex;   
    }   

    // Signal one waiting thread.   
    // must hold the external mutex before enter   
    int signal (void)   
    {   
        return pthread_cond_signal(&m_convar);
    }   

    // Signal *all* waiting threads.   
    // must hold the external mutex before enter   
    int broadcast (void)   
    {   
        return pthread_cond_broadcast(&m_convar);
    }   
        
    // must hold the external mutex before enter   
    int wait (unsigned long wait_time = -1)   
    {   
        struct timespec timeout;
        struct timeval  tv;
        gettimeofday(&tv , 0);
        timeout.tv_sec = wait_time / 1000 + tv.tv_sec + (wait_time % 1000 + tv.tv_usec / 1000) / 1000;
        timeout.tv_nsec = (wait_time % 1000 * 1000 + tv.tv_usec) % 1000000 * 1000;  
        return pthread_cond_timedwait(&m_convar, &m_mutex.handle(), &timeout);
    }
protected:   
    recursive_mutex &m_mutex;
    pthread_cond_t  m_convar;
}; 

#else

class semaphore
{   
public:   
    semaphore (long init_count, long max_count = 2147483647L)   
    {   
        assert (init_count >= 0 && max_count > 0 && init_count <= max_count);   
        m_sema = CreateSemaphoreA (NULL, init_count, max_count, NULL);   
    }   
    ~semaphore (void)   
    {   
        CloseHandle (m_sema);   
    }   
public:   
    int post (long count = 1)   
    {   
        BOOL bret = ReleaseSemaphore (m_sema, count, NULL);   
        return bret ? 0 : -1;   
    }   
    int wait (long timeout = -1)   
    {   
        DWORD ret = WaitForSingleObject (m_sema, timeout);   
        return ret == WAIT_OBJECT_0 ? 0 : -1;   
    }   
    HANDLE handle (void)   
    {   
        return m_sema;   
    }   
protected:   
    HANDLE m_sema;   
};   

class condition
{   
public:   
    condition (recursive_mutex &m)   
        : m_mutex (m)   
        , m_waiters (0)   
        , m_sema (0)   
    {   
    }   
    ~condition (void)   
    {   
    }   
public:   
    /// Returns a reference to the underlying mutex_;   
    recursive_mutex &mutex (void)   
    {   
        return m_mutex;   
    }   
    /// Signal one waiting thread.   
    //  must hold the external mutex before enter   
    int signal (void)   
    {   
        if ( m_waiters > 0 )   
            m_sema.post ();   
        return 0;   
    }   
    /// Signal *all* waiting threads.   
    //  must hold the external mutex before enter   
    int broadcast (void)   
    {   
        if ( m_waiters > 0 )   
            m_sema.post (m_waiters);   
        return 0;   
    }   
    //  must hold the external mutex before enter   
    int wait (unsigned long wait_time = -1)   
    {   
        int ret = 0;   
        m_waiters++; 
        m_mutex.leave();
        ret = WaitForSingleObject(m_sema.handle(), wait_time);
        m_mutex.enter ();   
        m_waiters --;   
        return ret == WAIT_OBJECT_0 ? 0 : -1;   
    }   
protected:   
    recursive_mutex &m_mutex;   
    /// Number of waiting threads.   
    long m_waiters;   
    /// Queue up threads waiting for the condition to become signaled.   
    semaphore m_sema;   
}; 


#endif




#endif // _BASE_SDK_THREAD_CONTITION_H_
